package com.demo.service.riot;

import com.demo.config.RiotConfig;
import com.demo.entity.riot.*;
import com.demo.exception.ApiException;
import com.demo.mapper.riot.MatchMapper;
import com.demo.service.riot.Async.MatchDataAsyncService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class RiotMatchService {
    private final RiotBasicService riotBasicService;
    private final MatchDataAsyncService matchDataAsyncService;
    private final RiotConfig riotConfig;

    private final String MATCH_IDS_BY_PUUID = "/lol/match/v5/matches/by-puuid/{puuid}/ids?start=0&count=10";
    private final String RANKED_MATCH_IDS_BY_PUUID = "/lol/match/v5/matches/by-puuid/{puuid}/ids?type=ranked&start=0&count=2";
    private final String MATCH_BY_ID = "/lol/match/v5/matches/{matchId}";

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Resource
    private MatchMapper matchMapper;

    public RiotMatchService(RiotBasicService riotBasicService, MatchDataAsyncService matchDataAsyncService, RiotConfig riotConfig) {
        this.riotBasicService = riotBasicService;
        this.matchDataAsyncService = matchDataAsyncService;
        this.riotConfig = riotConfig;
    }

    private List<MatchInfo> getMatchInfosByDB(String puuid) {
        return matchMapper.getMatchInfosByPuuid(puuid);
    }

    public List<MatchInfo> getMatchesByApi(String serverRegion, String puuid, Boolean rank) throws ApiException {
        List<String> matchIds = getMatchIdsByApi(serverRegion, puuid, rank);
        List<MatchInfo> matchInfos = new ArrayList<>();
        Map<String, String> pathParams;
        for (String matchId : matchIds) {
            pathParams = new HashMap<>();
            pathParams.put("serverRegion", serverRegion);
            pathParams.put("matchId", matchId);
            JsonNode jsonNode = riotBasicService.getJsonByParams(riotConfig, pathParams, null, serverRegion, MATCH_BY_ID, "对局详情", false);
            MatchInfo matchInfo = parseMatchInfo(jsonNode);
            matchInfos.add(matchInfo);
        }
        matchDataAsyncService.processMatchDataAsync(puuid, matchInfos);
        return matchInfos;
    }

    public List<MatchOverview> getMatches(String serverRegion, String puuid, Boolean rank) throws ApiException, IOException {
        List<MatchInfo> matchInfos = getMatchInfosByDB(puuid);
        if(matchInfos == null || matchInfos.isEmpty()) {
            matchInfos = getMatchesByApi(serverRegion, puuid, rank);
        } else {
            Timestamp timeStamp = new Timestamp(matchMapper.getLatesMatchCreationTime(puuid));
            LocalDateTime creation = timeStamp.toLocalDateTime();
            Duration duration = Duration.between(creation, LocalDateTime.now());
            if(duration.toHours() > 14 * 24) {
                matchInfos = getMatchesByApi(serverRegion, puuid, rank);
            }
        }
        List<MatchOverview> matchOverviews = new ArrayList<>();
        for (MatchInfo matchInfo : matchInfos) {
            matchOverviews.add(toMatchOverview(serverRegion, puuid, matchInfo));
        }
        return matchOverviews;
    }

    private List<MatchParticipant> toMatchParticipants(String serverRegion, MatchInfo matchInfo) throws IOException, ApiException {
        try {
            List<MatchParticipant> participants = new ArrayList<>();
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode root = objectMapper.readTree(matchInfo.getRawJson());
            JsonNode info = root.path("info");

            // 查找指定玩家的参与者节点
            for(JsonNode participantNode : info.path("participants")) {
                // 创建并填充MatchParticipant对象
                MatchParticipant participant = new MatchParticipant();
                participant.setGameName(participantNode.path("riotIdGameName").asText());
                participant.setTagLine(participantNode.path("riotIdTagline").asText());

                // 设置基础字段
                participant.setChampionId(participantNode.path("championId").asInt());
                participant.setChampionName(participantNode.path("championName").asText());
                participant.setChampionLevel(participantNode.path("champLevel").asInt());
                participant.setTeamId(participantNode.path("teamId").asInt());
                participant.setWin(participantNode.path("win").asBoolean());
                participant.setKills(participantNode.path("kills").asInt());
                participant.setDeaths(participantNode.path("deaths").asInt());
                participant.setAssists(participantNode.path("assists").asInt());
                participant.setKda(participantNode.path("challenges").path("kda").asDouble());

                // 设置位置信息
                participant.setTeamPosition(participantNode.path("teamPosition").asText());

                // 设置召唤师技能
                participant.setSummoner1(matchInfo.TransformSummoner(participantNode.path("summoner1Id").asInt()));
                participant.setSummoner2(matchInfo.TransformSummoner(participantNode.path("summoner2Id").asInt()));

                participant.setPerks(matchInfo.getPerks(participantNode));

                // 设置装备列表
                List<Integer> items = new ArrayList<>();
                for (int i = 0; i <= 6; i++) {
                    int itemId = participantNode.path("item" + i).asInt();
                    items.add(itemId);
                }
                participant.setItems(items);

                // 设置其他统计信息
                participant.setTotalDamageDealtToChampions(participantNode.path("totalDamageDealtToChampions").asInt());
                participant.setTotalDamageTaken(participantNode.path("totalDamageTaken").asInt());
                participant.setVisionWardsBoughtInGame(participantNode.path("visionWardsBoughtInGame").asInt());
                participant.setWardsKilled(participantNode.path("wardsKilled").asInt());
                participant.setWardsPlaced(participantNode.path("wardsPlaced").asInt());
                participant.setTotalMinionsKilled(participantNode.path("totalMinionsKilled").asInt());
                participant.setGoldEarned(participantNode.path("goldEarned").asInt());
                participants.add(participant);
            }

            return participants;

        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to parse match JSON for participant", e);
        }
    }

    private List<MatchTeam> toMatchTeams(String serverRegion, MatchInfo matchInfo) throws IOException, ApiException {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode root = objectMapper.readTree(matchInfo.getRawJson());
        JsonNode info = root.path("info");
        JsonNode teamsNode = info.path("teams");

        List<MatchTeam> teams = new ArrayList<>();

        // 处理每个队伍
        for (JsonNode teamNode : teamsNode) {
            MatchTeam team = new MatchTeam();

            // 设置基础队伍信息
            int teamId = teamNode.path("teamId").asInt();
            team.setTeamId(teamId);
            team.setWin("Win".equalsIgnoreCase(teamNode.path("win").asText()));

            // 处理禁用英雄
            List<MatchTeam.Ban> bans = new ArrayList<>();
            JsonNode bansNode = teamNode.path("bans");
            for (JsonNode banNode : bansNode) {
                MatchTeam.Ban ban = new MatchTeam.Ban();
                ban.setChampionId(banNode.path("championId").asInt());
                ban.setPickTurn(banNode.path("pickTurn").asInt());
                bans.add(ban);
            }
            team.setBans(bans);

            List<MatchParticipant> participants = toMatchParticipants(serverRegion, matchInfo);
            List<MatchParticipant> members = new ArrayList<>();
            Integer totalGold = 0;
            for (MatchParticipant participant : participants) {
                if(participant.getTeamId().equals(teamId)){
                    members.add(participant);
                    totalGold += participant.getGoldEarned();
                }
            }
            team.setMembers(members);
            team.setTotalGold(totalGold);

            // 处理目标数据
            Map<String, MatchTeam.Objective> objectives = new HashMap<>();
            JsonNode objectivesNode = teamNode.path("objectives");

            objectives.put("baron", matchInfo.createObjective(objectivesNode.path("baron")));
            objectives.put("champion", matchInfo.createObjective(objectivesNode.path("champion")));
            objectives.put("dragon", matchInfo.createObjective(objectivesNode.path("dragon")));
            objectives.put("inhibitor", matchInfo.createObjective(objectivesNode.path("inhibitor")));
            objectives.put("riftHerald", matchInfo.createObjective(objectivesNode.path("riftHerald")));
            objectives.put("tower", matchInfo.createObjective(objectivesNode.path("tower")));
            team.setObjectives(objectives);
            teams.add(team);
        }

        return teams;
    }

    private MatchOverview toMatchOverview(String serverRegion, String puuid, MatchInfo matchInfo) throws IOException, ApiException {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode root = objectMapper.readTree(matchInfo.getRawJson());

        // 1. 查找指定玩家的参与者数据
        JsonNode participantNode = matchInfo.findParticipant(root, puuid);
        if (participantNode == null) {
            throw new IllegalArgumentException("Player with puuid " + puuid + " not found in match " + matchInfo.getMatchId());
        }

        // 2. 创建并填充MatchOverview对象
        MatchOverview overview = new MatchOverview();

        // 2.1 从MatchInfo设置基础字段
        overview.setMatchId(matchInfo.getMatchId());
        overview.setGameCreation(matchInfo.getGameCreation());
        overview.setGameDuration(matchInfo.getGameDuration());
        overview.setGameMode(matchInfo.getGameMode());

        // 2.2 从参与者节点提取玩家特定数据
        overview.setChampionId(participantNode.path("championId").asInt());
        overview.setChampionName(participantNode.path("championName").asText());
        overview.setChampionLevel(participantNode.path("champLevel").asInt());
        overview.setWin(participantNode.path("win").asBoolean());
        overview.setKills(participantNode.path("kills").asInt());
        overview.setDeaths(participantNode.path("deaths").asInt());
        overview.setAssists(participantNode.path("assists").asInt());
        overview.setSummoner1(matchInfo.TransformSummoner(participantNode.path("summoner1Id").asInt()));
        overview.setSummoner2(matchInfo.TransformSummoner(participantNode.path("summoner2Id").asInt()));

        // 2.3 获取KDA
        overview.setKda(participantNode.path("challenges").path("kda").asDouble());

        // 2.4 提取装备列表
        List<Integer> items = new ArrayList<>();
        for (int i = 0; i <= 6; i++) {
            int itemId = participantNode.path("item" + i).asInt();
            items.add(itemId);
        }
        overview.setItems(items);

        overview.setParticipants(matchInfo.getTeamNode(root));

        overview.setPerks(matchInfo.getPerks(participantNode));

        List<MatchTeam> details = toMatchTeams(serverRegion, matchInfo);
        overview.setDetails(details);

        return overview;
    }

    private MatchInfo parseMatchInfo(JsonNode root) {
        JsonNode metadata = root.get("metadata");
        JsonNode info = root.get("info");

        MatchInfo matchInfo = new MatchInfo();

        // 提取必需字段
        matchInfo.setMatchId(metadata.path("matchId").asText(""));
        matchInfo.setGameCreation(info.path("gameCreation").asLong(0L));

        // 提取其他字段
        matchInfo.setGameDuration(Math.max(info.path("gameDuration").asInt(0), 1));
        matchInfo.setGameMode(info.path("gameMode").asText("UNKNOWN"));
        matchInfo.setGameType(info.path("gameType").asText("UNKNOWN"));
        matchInfo.setGameVersion(info.path("gameVersion").asText(""));
        matchInfo.setMapId(info.path("mapId").asInt(-1));
        matchInfo.setPlatformId(info.path("platformId").asText(""));
        matchInfo.setQueueId(info.path("queueId").asInt(0));
        matchInfo.setDataVersion(info.path("dataVersion").asText("1.0"));

        // 存储原始JSON
        matchInfo.setRawJson(root.toString());

        return matchInfo;
    }

    private List<String> getMatchIdsByApi(String serverRegion, String puuid, Boolean rank) throws ApiException {
        Map<String, String> pathParams = new HashMap<>();
        pathParams.put("puuid", puuid);
        JsonNode jsonNode;
        if(rank){
            jsonNode = riotBasicService.getJsonByParams(riotConfig, pathParams, null, serverRegion, RANKED_MATCH_IDS_BY_PUUID, "排位对局id", false);
        } else{
            jsonNode = riotBasicService.getJsonByParams(riotConfig, pathParams, null, serverRegion, MATCH_IDS_BY_PUUID, "对局id", false);
        }
        List<String> matchIds = new ArrayList<>();
        if(jsonNode != null){
            for(JsonNode element : jsonNode){
                matchIds.add(element.asText());
            }
        } else return null;
        return matchIds;
    }

}
